package com.azzcs.juc.stampedlock;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.StampedLock;

/**
 * @Author: wzg
 * @Date: 2021/6/21 上午9:52
 */
public class Main2 {
    private static volatile int num = 0;
    private static volatile AtomicInteger thread = new AtomicInteger();

    public static void main(String[] args) throws InterruptedException {
        StampedLock lock = new StampedLock();
        ExecutorService executor = Executors.newFixedThreadPool(100);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            if(i % 100 == 0) {
                executor.submit(() -> {
                    long stamp = lock.writeLock();
                    try{
                        TimeUnit.MILLISECONDS.sleep(50);
                        num++;
                        System.out.println("write "+ thread.incrementAndGet() +" ... "+ num);
                    }catch (Exception e){
                        e.printStackTrace();
                    }finally {
                        lock.unlockWrite(stamp);
                    }
                });
            }else {
                executor.submit(() -> {
                    boolean isLock = false;
                    long stamp = lock.tryOptimisticRead();
                    try {
                        TimeUnit.MILLISECONDS.sleep(50);
                        if (!lock.validate(stamp)) {
                            stamp = lock.readLock();
                            isLock = true;
                        }
                        System.out.println("read "+thread.incrementAndGet()+" ... " + num);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (isLock) {
                            lock.unlockRead(stamp);
                        }
                    }
                });
            }
        }

        executor.shutdown();
//        executor.shutdownNow();
        System.out.println("time is "+ (System.currentTimeMillis()-startTime));
        System.out.println("main ...");
    }
}
